﻿using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;

namespace NETXPF.Library
{
    public class Format
    {
        private static bool ranUnitTest = false;

        private Format() { }
        /// <summary>
        /// This removes characters that are invalid for xml encoding
        /// </summary>
        /// <param name="text">Text to be encoded.</param>
        /// <returns>Text with invalid xml characters removed.</returns>
        public static string CleanInvalidXmlChars(string text)
        {
            // From xml spec valid chars:
            // #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]    
            // any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
            string re = @"[^\x09\x0A\x0D\x20-\xD7FF\xE000-\xFFFD\x10000-x10FFFF]";
            return Regex.Replace(text, re, "");
        }
        public static double RoundToSigDigits(double d, int digits)
        {
            if (d == 0)
            {
                return d;
            }
            if (d < 0)
            {
                return -RoundToSigDigits(-d, digits);
            }
            double scale = Math.Pow(10.0, Math.Floor(Math.Log10(d)) + 1.0);
            return scale * Math.Round(d / scale, digits);
        }
        public static string FormatSigDigits(double n, int s)
        {
            return RoundToSigDigits(n, s).ToString("G7");
        }
        public static void UnitTestFormatSize()
        {
            if(!ranUnitTest)
            {
                // none of these cases should result in an exception:
                ranUnitTest = true;
                FormatSize(-1, 3);
                FormatSize(0, 0);
                FormatSize(0, 1);
                FormatSize(0, 3);
                FormatSize(1, 3);
                FormatSize(1024, 3);
                FormatSize(1048576, 3);
                FormatSize(1024*1048576, 3);
                FormatSize(1024*1048576, 0);
                FormatSize(-1024*1048576, 0);
                FormatSize(1024*1048576, 1);
                FormatSize(-1024*1048576, 1);
                FormatSize(-1024, 3);
                FormatSize(-1048576, 3);
                FormatSize(-1024*1048576, 3);
            }
        }
        public static string FormatSize(double size, int figures)
        {
            //self unit test
            UnitTestFormatSize();

            double tb = Math.Pow(2, 40);
            double gb = Math.Pow(2, 30);
            double mb = Math.Pow(2, 20);
            double kb = Math.Pow(2, 10);

            if (size >= tb)
            {
                return FormatSigDigits(size / tb, figures) + " TB";
            }
            if (size >= gb)
            {
                return FormatSigDigits(size / gb, figures) + " GB";
            }
            if (size >= mb)
            {
                return FormatSigDigits(size / mb, figures) + " MB";
            }
            if (size >= kb)
            {
                return FormatSigDigits(size / kb, figures) + " KB";
            }
            long sizeLong = (long)size;
            return sizeLong.ToString("D") + " bytes";
        }
    }
}
